﻿
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.IO;

namespace WebLibraryMaker
{
    class InterfaceBuilder
    {
        public static string Build(Pathes pathes, string[] assemblyPathes)
        {
            List<Assembly> assemblies = new List<Assembly>();

            foreach (string assemblyPath in assemblyPathes)
            {
                assemblies.Add(Assembly.LoadFrom(assemblyPath));
            }

            Assembly mainAssembly = assemblies[0];
            string mainName = mainAssembly.GetName().Name;

            CSharpCodeProvider CSharpProvider = new CSharpCodeProvider();
            CompilerParameters compilerParameters = new CompilerParameters();
            //Create a new Compiler parameter object.
            compilerParameters.GenerateExecutable = false;            
            compilerParameters.GenerateInMemory = false;
            compilerParameters.OutputAssembly = pathes.CompiledFileBillet + ".Interface.dll";

            //reference to System.dll is resuired in any case
            compilerParameters.ReferencedAssemblies.Add("System.dll");

            //reference to each App_Web_*.dll assembly
            foreach (string assemblyPath in assemblyPathes)
            {
                compilerParameters.ReferencedAssemblies.Add(assemblyPath);
            }

            //reference to each file used by the initial library
            foreach (AssemblyName assemblyName in mainAssembly.GetReferencedAssemblies())
            {
                Assembly assembly;

                try
                {
                    //standard assembly or GAC assembly
                    assembly = Assembly.Load(assemblyName);
                }
                catch 
                {
                    //custom assembly
                    assembly = Assembly.LoadFrom(assemblyName.Name + ".DLL");
                }

                if (String.Compare(Path.GetFileNameWithoutExtension(assembly.Location), "system", true) != 0)
                    compilerParameters.ReferencedAssemblies.Add(assembly.Location);
            }

            StringBuilder code = new StringBuilder();
            
            foreach (Assembly assembly in assemblies)
            {
                foreach (Type type in assembly.GetTypes())
                {
                    if (type.Namespace == "ASP" && !type.BaseType.Namespace.StartsWith("System."))
                    {
                        //create child class for each ASP.XX one
                        code.AppendLine("namespace " + type.BaseType.Namespace + " {");
                        code.AppendLine("public class " + type.BaseType.Name);
                        code.AppendLine(": " + type.Name);
                        code.AppendLine("{}");
                        code.AppendLine("}");
                    }
                }
            }

            if (code.Length != 0)
            {
                code.Insert(0, "using ASP;\r\n");
            }

            //compile the code
            CompilerResults compilerResult = CSharpProvider.CompileAssemblyFromSource(compilerParameters, code.ToString());
            if (compilerResult.Errors.Count > 0)
            {
                Console.WriteLine("Interface library creation error(s):");
                foreach (CompilerError error in compilerResult.Errors)
                {
                    Console.WriteLine(error.ErrorText);
                }

                return null;
            }

            return compilerParameters.OutputAssembly;
        }
    }
}
